﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.XPath;

namespace itau.imnk.transcritor
{
    public class Configuracoes
    {
        private static string PATH_XML_LISTA_CURVAS = "Configuracao/ListaCurvas";
        private static string PATH_XML_PARAM_EXEC = "Configuracao/ParametrosExecucao";
        private static string PATH_XML_EMAIL_ASSUNTO = "Configuracao/Email/Assunto";
        private static string PATH_XML_EMAIL_MSG = "Configuracao/Email/Mensagem";
        private static string PATH_XML_EMAIL_DESTINAT = "Configuracao/Email/Destinatarios";
        private static string PATH_XML_EMAIL_SERV = "Configuracao/Email/ServidorSMTP";
        private static string PATH_XML_EMAIL_REMET = "Configuracao/Email/Remetente";

        private XmlDocument _xmlDocument;
        private ConfiguracaoTranscricao _transcricao;
        private ConfiguracaoEmail _email;

        public Configuracoes()
        {
            string enderecoArquivoConfig = System.Configuration.ConfigurationSettings.AppSettings["ARQUIVO_CONFIG"];

            try
            {
                if (enderecoArquivoConfig != null)
                {
                    _xmlDocument = new XmlDocument();
                    _xmlDocument.Load(enderecoArquivoConfig);

                    _transcricao = new ConfiguracaoTranscricao(_xmlDocument);
                    _email = new ConfiguracaoEmail(_xmlDocument);
                }
                else
                {
                    throw new Exception("Chave para endereço do arquivo de configuração não encontrado.");
                }
            }
            catch (FileNotFoundException notFoundEx)
            {
                throw new Exception(string.Format("Arquivo de configuração não encontrado em: {0}", enderecoArquivoConfig), notFoundEx);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public ConfiguracaoTranscricao Transcricao
        {
            get
            {
                return _transcricao;
            }
        }

        public ConfiguracaoEmail Email
        {
            get
            {
                return _email;
            }
        }

        public sealed class ConfiguracaoTranscricao
        {
            XmlDocument _xmlDocument;

            public ConfiguracaoTranscricao(XmlDocument xmlDocument)
            {
                _xmlDocument = xmlDocument;
            }

            public IList<CurvaGravacao> CurvasGravacao
            {
                get
                {
                    IList<CurvaGravacao> curvaGravacao = new List<CurvaGravacao>();

                    XmlNode curvasXML = _xmlDocument.SelectSingleNode(PATH_XML_LISTA_CURVAS);

                    if (curvasXML != null)
                    {
                        string nomeCurvaIM;
                        string nomeYieldNK;
                        string tipoYieldNK;
                        string enderecoGravacao;

                        foreach (XmlNode curva in curvasXML.ChildNodes)
                        {
                            nomeCurvaIM = curva.Attributes["NomeCurvaIM"].Value;
                            nomeYieldNK = curva.Attributes["NomeYieldNK"].Value;
                            tipoYieldNK = curva.Attributes["TipoYieldNK"].Value;
                            enderecoGravacao = curva.Attributes["EnderecoGravacao"].Value;

                            if (nomeCurvaIM != null &&
                                nomeYieldNK != null &&
                                tipoYieldNK != null &&
                                enderecoGravacao != null)
                            {
                                curvaGravacao.Add(new CurvaGravacao()
                                {
                                    EnderecoGravacao = enderecoGravacao,
                                    NomeCurvaIM = nomeCurvaIM,
                                    NomeYieldNK = nomeYieldNK,
                                    TipoYieldNK = tipoYieldNK
                                });
                            }
                        }
                    }
                    else
                    {
                        throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_LISTA_CURVAS));
                    }

                    return curvaGravacao;
                }
            }

            public int TempoEsperaExecucao
            {
                get
                {
                    string parametro = ObterParametroExecucao("TempoEsperaExecucao");

                    return int.Parse(parametro ?? "0");
                }
            }

            public int TempoEntreImportacaoExecucao
            {
                get
                {
                    string parametro = ObterParametroExecucao("TempoEntreImportacaoExecucao");

                    return int.Parse(parametro ?? "0");
                }
            }

            public int TempoToleranciaParaObtencaoYield
            {
                get
                {
                    string parametro = ObterParametroExecucao("TempoToleranciaParaObtencaoYield");

                    return int.Parse(parametro ?? "0");
                }
            }

            public bool EnviarEmailToleranciaExtrapolada
            {
                get
                {
                    string parametro = ObterParametroExecucao("EnviarEmailToleranciaExtrapolada");

                    return Convert.ToBoolean(int.Parse(parametro ?? "0"));
                }
            }

            public bool StatusAtivo
            {
                get
                {
                    string parametro = ObterParametroExecucao("StatusAtivo");

                    return Convert.ToBoolean(int.Parse(parametro ?? "0"));
                }
            }

            public bool Custos
            {
                get
                {
                    string parametro = ObterParametroExecucao("Custos");

                    return Convert.ToBoolean(int.Parse(parametro ?? "0"));
                }
            }

            private string ObterParametroExecucao(string chave)
            {
                XmlNode parametrosExecucaoXML = _xmlDocument.SelectSingleNode(PATH_XML_PARAM_EXEC);

                if (parametrosExecucaoXML != null)
                {
                    var parametro = from xmlDoc in parametrosExecucaoXML.ChildNodes.Cast<XmlNode>()
                                    where xmlDoc.Attributes.Cast<XmlAttribute>().Count(p => p.Name.ToUpper() == "NOME" && p.Value == chave) > 0
                                    select xmlDoc;

                    if (parametro != null && parametro.Count() > 0)
                    {
                        XmlAttribute atributo = parametro.First().Attributes.Cast<XmlAttribute>().FirstOrDefault(p => p.Name.ToUpper() == "VALOR");

                        return atributo.Value;
                    }
                    else
                    {
                        throw new Exception(string.Format("Parâmetro de nome {0} não definido em {1} no arquivo de configuração", chave, PATH_XML_PARAM_EXEC));
                    }

                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_PARAM_EXEC));
                }
            }
        }

        public sealed class ConfiguracaoEmail
        {
            XmlDocument _xmlDocument;

            public ConfiguracaoEmail(XmlDocument xmlDocument)
            {
                _xmlDocument = xmlDocument;
            }

            public string ObterAssunto()
            {
                XmlNode assuntoXML = _xmlDocument.SelectSingleNode(PATH_XML_EMAIL_ASSUNTO);
                if (assuntoXML != null)
                {
                    return assuntoXML.InnerText;
                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_EMAIL_ASSUNTO));
                }
            }

            public string ObterMensagem()
            {
                XmlNode mensagemXML = _xmlDocument.SelectSingleNode(PATH_XML_EMAIL_MSG);
                if (mensagemXML != null)
                {
                    return mensagemXML.InnerText;
                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_EMAIL_MSG));
                }
            }

            public string ObterServidorSMTP()
            {
                XmlNode servidorXML = _xmlDocument.SelectSingleNode(PATH_XML_EMAIL_SERV);
                if (servidorXML != null)
                {
                    return servidorXML.InnerText;
                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_EMAIL_SERV));
                }
            }

            public string ObterRemetente()
            {
                XmlNode rementeXML = _xmlDocument.SelectSingleNode(PATH_XML_EMAIL_REMET);
                if (rementeXML != null)
                {
                    return rementeXML.InnerText;
                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_EMAIL_REMET));
                }
            }

            public List<string> ObterDestinatarios()
            {
                List<string> destinatarios = new List<string>();

                XmlNode listaDestinatariosXML = _xmlDocument.SelectSingleNode(PATH_XML_EMAIL_DESTINAT);
                if (listaDestinatariosXML != null)
                {
                    foreach (XmlNode destinatario in listaDestinatariosXML)
                    {
                        destinatarios.Add(destinatario.InnerText);
                    }
                }
                else
                {
                    throw new Exception(string.Format("{0} não definido no arquivo de configuração", PATH_XML_EMAIL_DESTINAT));
                }

                return destinatarios;
            }
        }

        public sealed class CurvaGravacao
        {
            public string NomeCurvaIM
            {
                get;
                set;
            }

            public string NomeYieldNK
            {
                get;
                set;
            }

            public string TipoYieldNK
            {
                get;
                set;
            }

            public string EnderecoGravacao
            {
                get;
                set;
            }
        }
    }
}
